"""
例1: 数组(Array)

定义：数组是一种基础的、线性的数据结构,用于在连续的内存空间中存储同一类型的数据。数组的每个元素都由索引来唯一标识,索引通常从0开始。

特性：
1. **连续内存空间与索引**：数组的所有元素在内存中都是连续的,这使得我们可以通过计算得到元素的内存地址,从而快速访问任意位置的元素。
2. **固定大小**：在创建数组时,必须指定其大小（即元素数量）。由于数组的长度在创建后就无法改变,所以我们需要确保在创建数组时给出的长度是足够的。

用途：
1. **数据存储**：由于数组能够存储大量的数据,并且能够快速访问,因此在需要大量数据存储和高效访问的场合下,常常会选择使用数组。
2. **缓冲区**：数组常常被用作缓冲区,因为它能够高效地存储和访问数据,满足缓冲区对效率的需求。

主要操作及步骤：

1. **插入元素**：由于数组的大小是固定的,所以插入元素时,通常需要在数组末尾添加元素。如果数组已满,我们需要先创建一个更大的数组,然后把原数组的元素复制到新数组中,再添加新元素。
2. **删除元素**：删除元素时,我们需要把被删除元素后面的所有元素向前移动一位。这个操作的时间复杂度是O(n),因为可能需要移动大量的元素。
3. **访问元素**：由于数组的内存是连续的,我们可以通过索引直接计算出元素的内存地址,从而快速访问元素。这个操作的时间复杂度是O(1)。
4. **查找元素**：数组中查找元素时,如果我们知道元素的索引,那么可以直接访问；如果我们不知道索引,那么就需要遍历数组,直到找到元素。这个操作的时间复杂度是O(n)。
5. **排序**：对数组排序时,我们可以使用各种排序算法,例如冒泡排序、选择排序、插入排序、快速排序等。这些排序算法的时间复杂度从O(n^2)到O(n log n)不等。
6. **合并**：合并两个数组时,我们需要创建一个新的数组,然后依次将两个数组的元素复制到新数组中。
"""
class Array:
    def __init__(self, length=0):
        self.array = [None]*length
        self.length = length

    # 2.1 Add/Push
    def add(self, value):
        self.array.append(value)
        self.length += 1

    # 2.2 Delete/Pop/Remove
    def delete(self, index):
        if index < 0:
            index = self.length + index
        if index >= self.length or index < 0:
            raise IndexError("Index out of range.")
        value = self.array[index]
        self.array = self.array[:index] + self.array[index+1:]
        self.length -= 1
        return value

    # 2.3 Get/Find/Peek
    def get(self, index):
        if index < 0:
            index = self.length + index
        if index >= self.length or index < 0:
            raise IndexError("Index out of range.")
        return self.array[index]

    # 2.4 Set/Add
    def set(self, index, value):
        if index < 0:
            index = self.length + index
        if index >= self.length or index < 0:
            raise IndexError("Index out of range.")
        self.array[index] = value

    # 2.5 Size, Length, Is_empty, Is_full
    def size(self):
        return self.length

    def is_empty(self):
        return self.length == 0

    # 2.8 Display structure with ASCII
    def print(self):
        print("[", end="")
        for i in range(self.length):
            if i != self.length - 1:
                print(self.array[i], end=", ")
            else:
                print(self.array[i], end="")
        print("]")

if __name__ == '__main__':
    # Create an array with length 10
    arr = Array(10)
    # Add an element
    arr.add(5)
    # Display the array
    arr.print()  # Outputs: [None, None, None, None, None, None, None, None, None, None, 5]
    # Access an element with negative index
    print(arr.get(-1))  # Outputs: 5
